/*
 * This file (ScriptVariableStore.java) is protected by the GNU GPL licence (v2). 
 * Please read the license.txt attached for further informations. 
 * 
 */
package org.algoristes.alkwarel.script;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * Stores ScriptVariables by name and scope
 * 
 * @author Xavier Gouchet
 * 
 */
public class ScriptVariableStore {

	private ArrayList<ScriptVariable> mStore;

	/**
	 * 
	 */
	public ScriptVariableStore() {
		mStore = new ArrayList<ScriptVariable>();
	}

	/**
	 * Prints the current Variable Store to {@link System}
	 * 
	 */
	public void print() {
		Iterator<ScriptVariable> it = mStore.iterator();
		ScriptVariable var = null;
		while (it.hasNext()) {
			var = it.next();
			System.out.println(var.mName + " : [" + var.mValue + "]");
		}
		System.out.println();
	}

	/**
	 * 
	 * @return the number of elements stored in this
	 */
	public int size() {
		return mStore.size();
	}

	/**
	 * Stores a variable in this
	 * 
	 * @param var
	 *            the variable to store
	 */
	public void put(ScriptVariable var) {
		if (var != null) {
			if (!mStore.contains(var))
				// no key with same name
				mStore.add(var);
			else {
				// key exist, only change its value
				int index = mStore.indexOf(var);
				ScriptVariable oldVar = mStore.get(index);
				oldVar.mValue = var.mValue;
			}
		}
	}

	/**
	 * Finds the best variable mathing the given name and return its value. If
	 * no variable is found, a RuntimeException is thrown.
	 * 
	 * @param name
	 *            the name of the value to find
	 * @param scope
	 *            the maximum depth of the variable
	 * @return the value of the nearest variable
	 */
	public String getValue(String name, int scope) {
		return getVariable(name, scope).mValue;
	}

	/**
	 * Finds the best variable mathing the given name. The variable which depth
	 * is nearest to scope is returned. If no variable is found, a
	 * RuntimeException is thrown.
	 * 
	 * @param name
	 *            the name of the value to find
	 * @param scope
	 *            the maximum depth of the variable
	 * @return the value of the nearest variable
	 */
	public ScriptVariable getVariable(String name, int scope) {
		Iterator<ScriptVariable> it = mStore.iterator();
		ScriptVariable var, best = null;
		while (it.hasNext()) {
			var = it.next();
			if (var.mName.equals(name)) {
				if ((best == null)
						|| ((var.getDepth() > best.getDepth()) && (var
								.getDepth() <= scope))) {
					best = var;
				}
			}
		}
		if (best == null)
			throw new RuntimeException("Unknown variable " + name);
		return best;
	}

	/**
	 * Removes all variable with a depth greater than the one provided
	 * 
	 * @param depth
	 *            the depth below which all variable are removed
	 */
	public void cleanVariables(int depth) {
		ScriptVariable var;
		for (int i = mStore.size() - 1; i >= 0; i--) {
			var = mStore.get(i);
			if (var.getDepth() >= depth)
				mStore.remove(var);
		}
	}

	/**
	 * Checks if the store contains a variable with the given name
	 * 
	 * @param name
	 *            the name to look for
	 * @return if the variable exists
	 */
	public boolean contains(String name) {
		ScriptVariable var = new ScriptVariable(name, "", 0);
		return mStore.contains(var);
	}
}
